package org.example.springboot.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import org.example.springboot.DTO.BorrowDTO;
import org.example.springboot.entity.Book;
import org.example.springboot.entity.BorrowRecord;
import org.example.springboot.entity.User;
import org.example.springboot.enumClass.BorrowStatus;
import org.example.springboot.exception.ServiceException;
import org.example.springboot.mapper.BookMapper;
import org.example.springboot.mapper.BorrowRecordMapper;
import org.example.springboot.mapper.UserMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 借阅记录服务类
 */
@Service
public class BorrowRecordService {
    @Resource
    private BorrowRecordMapper borrowRecordMapper;
    
    @Resource
    private BookMapper bookMapper;
    
    @Resource
    private UserMapper userMapper;
    
    @Resource
    private SysConfigService configService;
    
    /**
     * 借阅图书
     * @param userId 用户ID
     * @param borrowDTO 借阅信息
     * @return 借阅记录
     */
    @Transactional(rollbackFor = Exception.class)
    public BorrowRecord borrowBook(Long userId, BorrowDTO borrowDTO) {
        // 检查用户是否存在
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new ServiceException("用户不存在");
        }
        
        // 检查图书是否存在
        Book book = bookMapper.selectById(borrowDTO.getBookId());
        if (book == null) {
            throw new ServiceException("图书不存在");
        }
        
        // 检查图书是否上架
        if (book.getStatus() != 1) {
            throw new ServiceException("图书已下架，无法借阅");
        }
        
        // 检查图书库存
        if (book.getStock() <= 0) {
            throw new ServiceException("图书库存不足，无法借阅");
        }
        
        // 检查用户是否已借阅该图书
        LambdaQueryWrapper<BorrowRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BorrowRecord::getUserId, userId)
                .eq(BorrowRecord::getBookId, borrowDTO.getBookId())
                .in(BorrowRecord::getStatus, 
                    BorrowStatus.PENDING_APPROVAL.getValue(), 
                    BorrowStatus.OVERDUE.getValue(),
                    BorrowStatus.BORROWING.getValue());
        if (borrowRecordMapper.selectCount(queryWrapper) > 0) {
            throw new ServiceException("您已有该图书的借阅申请或已借阅该图书，无法重复借阅");
        }
        
        // 检查用户借阅数量是否超过限制
        int maxBorrowBooks = Integer.parseInt(configService.getConfigValue("borrow.max_books", "5"));
        queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BorrowRecord::getUserId, userId)
                .in(BorrowRecord::getStatus, 
                    BorrowStatus.PENDING_APPROVAL.getValue(), 
                    BorrowStatus.OVERDUE.getValue(),
                    BorrowStatus.BORROWING.getValue());
        if (borrowRecordMapper.selectCount(queryWrapper) >= maxBorrowBooks) {
            throw new ServiceException("您的借阅申请或借阅数量已达上限，无法继续借阅");
        }
        
        // 计算借阅天数和归还时间
        int borrowDays = borrowDTO.getDays() != null ? borrowDTO.getDays() : 
                Integer.parseInt(configService.getConfigValue("borrow.max_days", "30"));
        
        // 创建借阅记录
        BorrowRecord borrowRecord = new BorrowRecord();
        borrowRecord.setUserId(userId);
        borrowRecord.setBookId(borrowDTO.getBookId());
        borrowRecord.setBorrowTime(Timestamp.valueOf(LocalDateTime.now()));
        
        // 计算计划归还时间
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, borrowDays);
        borrowRecord.setPlanReturnTime(new Timestamp(calendar.getTimeInMillis()));
        
        borrowRecord.setRenewCount(0);
        // 设置状态为待审核
        borrowRecord.setStatus(BorrowStatus.PENDING_APPROVAL.getValue());
        
        // 保存借阅记录
        borrowRecordMapper.insert(borrowRecord);
        
        // 临时预扣库存（可选，也可以在审核通过后再扣除库存）
        book.setStock(book.getStock() - 1);
        bookMapper.updateById(book);
        
        // 填充返回信息
        borrowRecord.setBookTitle(book.getTitle());
        borrowRecord.setCoverUrl(book.getCoverUrl());
        borrowRecord.setAuthor(book.getAuthor());
        
        return borrowRecord;
    }
    
    /**
     * 归还图书
     * @param userId 用户ID
     * @param borrowId 借阅记录ID
     * @return 借阅记录
     */
    @Transactional(rollbackFor = Exception.class)
    public BorrowRecord returnBook(Long userId, Long borrowId) {
        // 查询借阅记录
        BorrowRecord borrowRecord = borrowRecordMapper.selectById(borrowId);
        if (borrowRecord == null) {
            throw new ServiceException("借阅记录不存在");
        }
        
        // 检查是否是当前用户的借阅记录
        if (!borrowRecord.getUserId().equals(userId)) {
            throw new ServiceException("无权操作此借阅记录");
        }
        
        // 检查借阅状态
        if (borrowRecord.getStatus() != BorrowStatus.BORROWING.getValue() &&
            borrowRecord.getStatus() != BorrowStatus.OVERDUE.getValue()) {
            throw new ServiceException("该图书尚未借出或已归还，无需归还");
        }
        
        // 更新借阅记录
        borrowRecord.setActualReturnTime(Timestamp.valueOf(LocalDateTime.now()));
        borrowRecord.setStatus(BorrowStatus.RETURNED.getValue());
        borrowRecordMapper.updateById(borrowRecord);
        
        // 更新图书库存
        Book book = bookMapper.selectById(borrowRecord.getBookId());
        if (book != null) {
            book.setStock(book.getStock() + 1);
            bookMapper.updateById(book);
        }
        
        return borrowRecord;
    }
    
    /**
     * 续借图书
     * @param userId 用户ID
     * @param borrowId 借阅记录ID
     * @return 借阅记录
     */
    @Transactional(rollbackFor = Exception.class)
    public BorrowRecord renewBook(Long userId, Long borrowId) {
        // 查询借阅记录
        BorrowRecord borrowRecord = borrowRecordMapper.selectById(borrowId);
        if (borrowRecord == null) {
            throw new ServiceException("借阅记录不存在");
        }
        
        // 检查是否是当前用户的借阅记录
        if (!borrowRecord.getUserId().equals(userId)) {
            throw new ServiceException("无权操作此借阅记录");
        }
        
        // 检查借阅状态
        if (borrowRecord.getStatus() != BorrowStatus.BORROWING.getValue()) {
            throw new ServiceException("只有借阅中的图书才能续借");
        }
        
        // 检查续借次数是否超过限制
        int maxRenew = Integer.parseInt(configService.getConfigValue("borrow.max_renew", "2"));
        if (borrowRecord.getRenewCount() >= maxRenew) {
            throw new ServiceException("续借次数已达上限，无法继续续借");
        }
        
        // 更新借阅记录
        int borrowDays = Integer.parseInt(configService.getConfigValue("borrow.max_days", "30"));
        
        // 计算新的计划归还时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(borrowRecord.getPlanReturnTime().getTime());
        calendar.add(Calendar.DATE, borrowDays);
        borrowRecord.setPlanReturnTime(new Timestamp(calendar.getTimeInMillis()));
        
        borrowRecord.setRenewCount(borrowRecord.getRenewCount() + 1);
        borrowRecordMapper.updateById(borrowRecord);
        
        return borrowRecord;
    }
    
    /**
     * 取消借阅申请
     * @param userId 用户ID
     * @param borrowId 借阅记录ID
     * @return 借阅记录
     */
    @Transactional(rollbackFor = Exception.class)
    public BorrowRecord cancelBorrow(Long userId, Long borrowId) {
        // 查询借阅记录
        BorrowRecord borrowRecord = borrowRecordMapper.selectById(borrowId);
        if (borrowRecord == null) {
            throw new ServiceException("借阅记录不存在");
        }
        
        // 检查是否是当前用户的借阅记录
        if (!borrowRecord.getUserId().equals(userId)) {
            throw new ServiceException("无权操作此借阅记录");
        }
        
        // 检查借阅状态
        if (borrowRecord.getStatus() != BorrowStatus.PENDING_APPROVAL.getValue() && 
            borrowRecord.getStatus() != BorrowStatus.REJECTED.getValue()) {
            throw new ServiceException("只有待审核或已审核的记录才能取消借阅申请");
        }
        
        // 更新借阅记录
        borrowRecord.setStatus(BorrowStatus.CANCELED.getValue());
        borrowRecordMapper.updateById(borrowRecord);
        
        // 更新图书库存
        Book book = bookMapper.selectById(borrowRecord.getBookId());
        if (book != null) {
            book.setStock(book.getStock() + 1);
            bookMapper.updateById(book);
        }
        
        return borrowRecord;
    }
    
    /**
     * 查询用户的借阅记录
     * @param userId 用户ID
     * @param status 状态
     * @param currentPage 当前页
     * @param size 每页大小
     * @return 分页结果
     */
    public Page<BorrowRecord> getUserBorrowRecords(Long userId, Integer status, Integer currentPage, Integer size) {
        LambdaQueryWrapper<BorrowRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BorrowRecord::getUserId, userId);
        
        if (status != null) {
            queryWrapper.eq(BorrowRecord::getStatus, status);
        }
        
        queryWrapper.orderByDesc(BorrowRecord::getCreateTime);
        
        Page<BorrowRecord> page = borrowRecordMapper.selectPage(new Page<>(currentPage, size), queryWrapper);
        
        // 填充图书信息
        for (BorrowRecord record : page.getRecords()) {
            Book book = bookMapper.selectById(record.getBookId());
            if (book != null) {
                record.setBookTitle(book.getTitle());
                record.setCoverUrl(book.getCoverUrl());
                record.setAuthor(book.getAuthor());
            }
        }
        
        return page;
    }
    
    /**
     * 查询所有借阅记录（管理员使用）
     * @param userId 用户ID
     * @param bookId 图书ID
     * @param status 状态
     * @param currentPage 当前页
     * @param size 每页大小
     * @return 分页结果
     */
    public Page<BorrowRecord> getAllBorrowRecords(Long userId, Long bookId,String bookName, Integer status, Integer currentPage, Integer size) {
        LambdaQueryWrapper<BorrowRecord> queryWrapper = new LambdaQueryWrapper<>();
        
        if (userId != null) {
            queryWrapper.eq(BorrowRecord::getUserId, userId);
        }
        
        if (bookId != null) {
            queryWrapper.eq(BorrowRecord::getBookId, bookId);
        }
        
        if (status != null) {
            queryWrapper.eq(BorrowRecord::getStatus, status);
        }
        if(StringUtils.isNotBlank(bookName)){
           List<Long> bookIds= bookMapper.selectList(new LambdaQueryWrapper<Book>().eq(Book::getTitle, bookName)).stream().map(Book::getId).toList();
           queryWrapper.in(BorrowRecord::getBookId, bookIds);
        }
        
        queryWrapper.orderByDesc(BorrowRecord::getCreateTime);
        
        Page<BorrowRecord> page = borrowRecordMapper.selectPage(new Page<>(currentPage, size), queryWrapper);
        
        // 填充图书和用户信息
        for (BorrowRecord record : page.getRecords()) {
            Book book = bookMapper.selectById(record.getBookId());
            if (book != null) {
                record.setBookTitle(book.getTitle());
                record.setCoverUrl(book.getCoverUrl());
                record.setAuthor(book.getAuthor());
            }
            
            User user = userMapper.selectById(record.getUserId());
            if (user != null) {
                record.setUsername(user.getUsername());
            }
        }
        
        return page;
    }
    
    /**
     * 检查并更新逾期状态
     */
    public void checkAndUpdateOverdueStatus() {
        // 查询所有借阅中且已过期的记录
        LambdaQueryWrapper<BorrowRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BorrowRecord::getStatus, BorrowStatus.BORROWING.getValue())
                .lt(BorrowRecord::getPlanReturnTime, new Timestamp(System.currentTimeMillis()));
        
        List<BorrowRecord> overdueRecords = borrowRecordMapper.selectList(queryWrapper);
        
        // 更新状态为逾期
        for (BorrowRecord record : overdueRecords) {
            record.setStatus(BorrowStatus.OVERDUE.getValue());
            borrowRecordMapper.updateById(record);
        }
    }
    
    /**
     * 获取借阅记录详情
     * @param id 借阅记录ID
     * @return 借阅记录
     */
    public BorrowRecord getBorrowRecordById(Long id) {
        BorrowRecord borrowRecord = borrowRecordMapper.selectById(id);
        if (borrowRecord == null) {
            throw new ServiceException("借阅记录不存在");
        }
        
        // 填充图书信息
        Book book = bookMapper.selectById(borrowRecord.getBookId());
        if (book != null) {
            borrowRecord.setBookTitle(book.getTitle());
            borrowRecord.setCoverUrl(book.getCoverUrl());
            borrowRecord.setAuthor(book.getAuthor());
        }
        
        // 填充用户信息
        User user = userMapper.selectById(borrowRecord.getUserId());
        if (user != null) {
            borrowRecord.setUsername(user.getUsername());
        }
        
        return borrowRecord;
    }

    /**
     * 审核通过借阅申请
     * @param borrowId 借阅记录ID
     * @return 借阅记录
     */
    @Transactional(rollbackFor = Exception.class)
    public BorrowRecord approveBook(Long borrowId) {
        // 查询借阅记录
        BorrowRecord borrowRecord = borrowRecordMapper.selectById(borrowId);
        if (borrowRecord == null) {
            throw new ServiceException("借阅记录不存在");
        }
        
        // 检查借阅状态
        if (borrowRecord.getStatus() != BorrowStatus.PENDING_APPROVAL.getValue()) {
            throw new ServiceException("只有待审核的借阅记录才能审核通过");
        }
        
        // 更新借阅状态为借阅中
        borrowRecord.setStatus(BorrowStatus.BORROWING.getValue());
        
        // 更新借阅时间为当前时间(如有需要)
        borrowRecord.setBorrowTime(Timestamp.valueOf(LocalDateTime.now()));
        
        // 重新计算预计归还时间(根据当前时间计算)
        Calendar calendar = Calendar.getInstance();
        int borrowDays = (int) ChronoUnit.DAYS.between(
            borrowRecord.getBorrowTime().toLocalDateTime(),
            borrowRecord.getPlanReturnTime().toLocalDateTime());
        if (borrowDays <= 0) { // 如果计算出来的天数不正确，使用默认天数
            borrowDays = Integer.parseInt(configService.getConfigValue("borrow.max_days", "30"));
        }
        calendar.add(Calendar.DATE, borrowDays);
        borrowRecord.setPlanReturnTime(new Timestamp(calendar.getTimeInMillis()));
        
        borrowRecordMapper.updateById(borrowRecord);
        
        // 更新图书借阅次数
        Book book = bookMapper.selectById(borrowRecord.getBookId());
        if (book != null) {
            book.setBorrowedCount(book.getBorrowedCount() + 1);
            bookMapper.updateById(book);
        }
        
        return borrowRecord;
    }

    /**
     * 审核拒绝借阅申请
     * @param borrowId 借阅记录ID
     * @return 借阅记录
     */
    @Transactional(rollbackFor = Exception.class)
    public BorrowRecord rejectBook(Long borrowId) {
        // 查询借阅记录
        BorrowRecord borrowRecord = borrowRecordMapper.selectById(borrowId);
        if (borrowRecord == null) {
            throw new ServiceException("借阅记录不存在");
        }
        
        // 检查借阅状态
        if (borrowRecord.getStatus() != BorrowStatus.PENDING_APPROVAL.getValue()) {
            throw new ServiceException("只有待审核的借阅记录才能审核拒绝");
        }
        
        // 更新借阅状态为审核拒绝
        borrowRecord.setStatus(BorrowStatus.REJECTED.getValue());
        borrowRecordMapper.updateById(borrowRecord);
        
        // 恢复图书库存
        Book book = bookMapper.selectById(borrowRecord.getBookId());
        if (book != null) {
            book.setStock(book.getStock() + 1);
            bookMapper.updateById(book);
        }
        
        // 记录审核信息（可以添加审核记录表，记录审核人、审核时间、拒绝原因等信息）
        
        return borrowRecord;
    }
} 